Next | Prev | Up | Top | Contents | Index
Mutual Exclusion Macros
The macros for mutual exclusion defined in net/if.h are listed in Table 16-2.
Mutual Exclusion Macros for ifnet Drivers
Macro Prototype | Purpose |
---|
IFNET_LOCK(ifp, s) | Get exclusive use of the structure *ifp. splimp() is called to raise the interrupt level if necessary, and the returned value is saved in s. |
IFNET_UNLOCK(ifp,s) | Release use of *ifp, and return to interrupt level s. |
IFNET_LOCKNOSPL(ifp) | Get exclusive use of the structure *ifp, but do not call splimp() (the driver knows it is already at the appropriate level.) |
IFNET_UNLOCKNOSPL(ifp) | Release use of *ifp after use of IFNET_LOCKNOSPL. |
IFNET_ISLOCKED(ifp) | Test whether *ifp is locked. |
IFQ_LOCK(ifq) | Get exclusive use of an input queue *ifq. |
IFQ_UNLOCK(ifq) | Release use of *ifq. |
IF_ENQUEUE(ifq, mp) | Lock the queue *ifq; post the mbuf *mp; release the queue. |
IF_ENQUEUE_NOLOCK(ifq,mp) | Post the mbuf *mp without locking. |
The variables used in Table 16-2 are as follows:
ifp | Address of a struct ifnet to be used exclusively. |
s | Integer variable to store the current interrupt mask level. |
ifq | Address of a struct ifqueue to be posted. |
mp | Address of a struct mbuf to be posted. |
Macro Use
The TCP/IP protocol stack automatically acquires the ifnet structure before calling a network driver routine through that structure. Thus the driver's init(), stop(), start(), output(), and ioctl() functions do not need to use IFNET_LOCK or IFNET_UNLOCK. Look for expressions
ASSERT(IFNET_ISLOCKED(ifp));
in the example driver ("Example ifnet Driver") to see places where this is the case. Explicit use of IFNET_LOCK is needed in the interrupt handler.
Input Queueing Example
Example 16-1 displays a code fragment of an interrupt handler that queues an input packet pointed to by m onto the IP input queue. The function schednetisr() is called to schedule processing of that packet. The code is assumed to be already at splimp().
Example 16-1 : Input Queueing Using Locking Macros
{
...
ifq = &ipintrq; /* the ip protocol queue */
/*
* If queue is full, we drop the packet.
*/
IFQ_LOCK(ifq);
if (IF_QFULL(ifq)) {
m_freem(m);
IF_DROP(ifq);
IFQ_UNLOCK(ifq);
return(-1);
}
IF_ENQUEUE_NOLOCK(ifq, m);
schednetisr(NETISR_IP); /* schedule ip interrupt */
IFQ_UNLOCK(ifq);
return(0);
}
Interrupt Handler Example
Example 16-2 displays the skeleton of an Ethernet interrupt handler.
Example 16-2 : Interrupt Handling Using Locking Macros
/*
* Ethernet interface interrupt.
*/
if_etintr(int unit)
{
ETIO io;
struct et_info *ei;
register int s = splimp(); /* get the spin lock */
ASSERT(unit == 0);
ei = &et_info;
io = ei->ei_io;
if (io == 0) { /* ignore early interrupts */
printf("et0: early interrupt\n");
splx(s);
return 1;
}
IFNET_LOCKNOSPL(&ei->ei_if);
et_poll(ei);
IFNET_UNLOCKNOSPL(&ei->ei_if);
splx(s);
}
Next | Prev | Up | Top | Contents | Index